// SendMailTest.cpp
 
#include "email.h"
 
#include <iostream> 
#include <string>

#ifdef WIN32
#pragma comment(lib, "ws2_32.lib")
#endif //

#ifdef __linux__
#define Sleep sleep
#define closesocket close

#define sprintf_s(buffer, size, arg...) \
	do{ sprintf(buffer, ##arg); } while (0) 
#endif // __linux__

#include "pfunc.h"
#include "business_def.h"


Email::Email(/* args */)
{
  BusinessDef* pbd = BusinessDef::getInstance();
  email_conf = pbd->getEmailConf();
  area_desc = pbd->getAreaInfo().areaDesc;
}

Email::~Email()
{
}

bool Email::isMapMailTime()
{
    //you code
    return pyfree::isMapTime(email_conf.startTime,email_conf.endTime);
};

void Email::send_email(EventForWaring efw)
{
    char comment_buf[512] = { 0 };
    sprintf(comment_buf
        , "{"
        "\"ETime\":\"%s\""
        ",\"ADesc\":\"%s\""
        ",\"EType\":\"%s\""
        ",\"ELevel\":\"%s\""
        ",\"TaskID\":\"%s\""
        ",\"DevID\":\"%s\""
        ",\"PID\":\"%s\""
        ",\"ValDesc\":\"%s\""
        "}"
        , efw.execTime.c_str()
        , area_desc.c_str()
        , efw.desc.c_str()
        , efw.levelDesc.c_str()
        , efw.taskDesc.c_str()
        , efw.devDesc.c_str()
        , efw.pDesc.c_str()
        , efw.valDesc.c_str()
    );
    send_email(std::string(comment_buf));
}

void Email::send_email(std::string comment)
{
    std::string from_desc = "From: \""+email_conf.email_from.email_user+"\"<"+email_conf.email_from.email_addr+">\r\n";
    std::string comment_desc = "Subject:"+ email_conf.email_from.email_title+"\r\n\r\n"+ comment+"\n";
    for(std::vector<pyfree::Email_User_To>::iterator it = email_conf.email_to.begin();it!=email_conf.email_to.end();++it)
    {
        std::string to_desc = "To: \""+it->email_user+"\"<"+it->email_addr+">\r\n";
        std::string EmailContents = from_desc+to_desc+comment_desc;
        Print_NOTICE("send comment:\n%s", EmailContents.c_str());
        this->sendEmail((char*)it->email_addr.c_str(), EmailContents.c_str()
            , (char*)email_conf.email_from.email_addr.c_str()
            , (char*)email_conf.email_from.email_key.c_str());
    }
}

// 发送邮件
void Email::sendEmail(char *emailTo, const char *body,char* emailFrom, char* emailKey)
{
  int   sockfd = { 0 };
  char  buf[1500] = { 0 };
  char  rbuf[1500] = { 0 };
  char  login[128] = { 0 };
  char  pass[128] = { 0 };
  
  struct sockaddr_in their_addr;
#ifdef WIN32
  WSADATA WSAData;
  WSAStartup(MAKEWORD(2, 2), &WSAData);
#endif // WIN32
  memset(&their_addr, 0, sizeof(their_addr));
 
  their_addr.sin_family = AF_INET;
  // their_addr.sin_port = htons(25);					 // 一般是25端口不需要改
  their_addr.sin_port = htons(email_conf.email_srv.email_port);					 // 一般是25端口不需要改
  // hostent* hptr = gethostbyname("smtp.163.com");     // 端口和服务器
  hostent* hptr = gethostbyname(email_conf.email_srv.email_host.c_str());     // 端口和服务器
#ifdef WIN32
  memcpy(&their_addr.sin_addr.S_un.S_addr, hptr->h_addr_list[0], hptr->h_length);
  Print_NOTICE("IP of %s is : %d:%d:%d:%d\n",
    email_conf.email_srv.email_host.c_str(),
	  their_addr.sin_addr.S_un.S_un_b.s_b1,
	  their_addr.sin_addr.S_un.S_un_b.s_b2,
	  their_addr.sin_addr.S_un.S_un_b.s_b3,
	  their_addr.sin_addr.S_un.S_un_b.s_b4);
#else
  memcpy(&their_addr.sin_addr.s_addr, hptr->h_addr_list[0], hptr->h_length);
  Print_NOTICE("IP of %s is : %d:%d:%d:%d\n",
    email_conf.email_srv.email_host.c_str(),
	  their_addr.sin_addr.s_addr & 0XFF,
	  their_addr.sin_addr.s_addr>>8 & 0XFF,
	  their_addr.sin_addr.s_addr>>16 & 0XFF,
	  their_addr.sin_addr.s_addr>>24 & 0XFF);
#endif
  // 连接邮件服务器，如果连接后没有响应，则2 秒后重新连接
  sockfd = openEmailSocket((struct sockaddr *)&their_addr);
  memset(rbuf, 0, 1500);
  while (recv(sockfd, rbuf, 1500, 0) == 0)
  {
    std::cout << "reconnect..." << std::endl;
    Sleep(2);
    sockfd = openEmailSocket((struct sockaddr *)&their_addr);
    memset(rbuf, 0, 1500);
  }
  if(sockfd<0)
  {
    return;
  }
 
  std::cout << rbuf << std::endl;
 
  // EHLO
  memset(buf, 0, 1500);
  sprintf_s(buf, 1500, "EHLO HYL-PC\r\n");
  send(sockfd, buf, (int)strlen(buf), 0);
  memset(rbuf, 0, 1500);
  recv(sockfd, rbuf, 1500, 0);
  std::cout << "EHLO REceive: " << rbuf << std::endl;
 
  // AUTH LOGIN
  memset(buf, 0, 1500);
  sprintf_s(buf, 1500, "AUTH LOGIN\r\n");
  send(sockfd, buf, (int)strlen(buf), 0);
  memset(rbuf, 0, 1500);
  recv(sockfd, rbuf, 1500, 0);
  std::cout << "Auth Login Receive: " << rbuf << std::endl;
 
  // USER
  memset(buf, 0, 1500);
  sprintf_s(buf, 1500, "%s",emailFrom);//你的邮箱账号
  memset(login, 0, 128);
  pyfree::EncodeBase64(login, buf, (int)strlen(buf));
  sprintf_s(buf, 1500, "%s\r\n", login);
  send(sockfd, buf, (int)strlen(buf), 0);
  std::cout << "Base64 UserName: " << buf << std::endl;
  memset(rbuf, 0, 1500);
  recv(sockfd, rbuf, 1500, 0);
  std::cout << "User Login Receive: " << rbuf << std::endl;
 
  // PASSWORD
  sprintf_s(buf, 1500, "%s",emailKey);//你的邮箱密码
  memset(pass, 0, 128);
  pyfree::EncodeBase64(pass, buf, (int)strlen(buf));
  sprintf_s(buf, 1500, "%s\r\n", pass);
  send(sockfd, buf, (int)strlen(buf), 0);
  std::cout << "Base64 Password: " << buf << std::endl;
 
  memset(rbuf, 0, 1500);
  recv(sockfd, rbuf, 1500, 0);
  std::cout << "Send Password Receive: " << rbuf << std::endl;
 
  // MAIL FROM
  memset(buf, 0, 1500);
  sprintf_s(buf, 1500, "MAIL FROM: <%s>\r\n",emailFrom); //此处要和发邮件的邮箱保持一致
  send(sockfd, buf, (int)strlen(buf), 0);
  memset(rbuf, 0, 1500);
  recv(sockfd, rbuf, 1500, 0);
  std::cout << "set Mail From Receive: " << rbuf << std::endl;
 
  // RCPT TO 第一个收件人
  sprintf_s(buf, 1500, "RCPT TO:<%s>\r\n", emailTo);
  send(sockfd, buf, (int)strlen(buf), 0);
  memset(rbuf, 0, 1500);
  recv(sockfd, rbuf, 1500, 0);
  std::cout << "Tell Sendto Receive: " << rbuf << std::endl;
 
  // DATA 准备开始发送邮件内容
  sprintf_s(buf, 1500, "DATA\r\n");
  send(sockfd, buf, (int)strlen(buf), 0);
  memset(rbuf, 0, 1500);
  recv(sockfd, rbuf, 1500, 0);
  std::cout << "Send Mail Prepare Receive: " << rbuf << std::endl;
 
  // 发送邮件内容，\r\n.\r\n内容结束标记
  sprintf_s(buf, 1500, "%s\r\n.\r\n", body);
  send(sockfd, buf, (int)strlen(buf), 0);
  memset(rbuf, 0, 1500);
  recv(sockfd, rbuf, 1500, 0);
  std::cout << "Send Mail Receive: " << rbuf << std::endl;
 
  // QUIT
  sprintf_s(buf, 1500, "QUIT\r\n");
  send(sockfd, buf, (int)strlen(buf), 0);
  memset(rbuf, 0, 1500);
  recv(sockfd, rbuf, 1500, 0);
  std::cout << "Quit Receive: " << rbuf << std::endl;
 
  //清理工作
  closesocket(sockfd);
#ifdef WIN32
  WSACleanup();
#endif
  return;
}
// 打开TCP Socket连接
int Email::openEmailSocket(struct sockaddr *addr)
{
  int sockfd = 0;
  sockfd = (int)socket(PF_INET, SOCK_STREAM, 0);
  if (sockfd < 0)
  {
    std::cout << "Open sockfd(TCP) error!" << std::endl;
    return -1;
  }
  if (connect(sockfd, addr, sizeof(struct sockaddr)) < 0)
  {
    std::cout << "Connect sockfd(TCP) error!" << std::endl;
    return -1;
  }
  return sockfd;
}